Der Architekturansatz ermöglicht es, Use-Case-getrieben vorzugehen und fachliche Anforderungen effizient umzusetzen. Als einfachere Alternative zu etablierten Architekturstilen wie Hexagonal, Onion und Clean Architecture gewinnt er zunehmend an Beliebtheit. Wir werfen einen ersten Blick auf das Konzept.
Die Vertical Slice Architecture wurde von Jimmy Bogard, dem Entwickler des MediatoR-Frameworks, entworfen. Bei der Arbeit mit der Onion Architecture stieß Bogard auf Herausforderungen, die ihn dazu veranlassten, neue Wege zur Codeorganisation zu erforschen.
Herausforderungen der Schichtenarchitekturen
Hexagonale, Onion und Clean Architecture sind Weiterentwicklungen der klassischen Schichtenarchitektur, die sich in mehrere getrennte Schichten wie Datenzugriff, Geschäftslogik und Präsentation gliedert.
Änderungen verursachen bei allen drei Architekturstilen dieselben Probleme und Aufwände.
Modifikationen oder Erweiterungen der Anwendung erfordern oft Anpassungen in mehreren Schichten. Eine Erweiterung der Anzeige um ein Feld zum Beispiel könnte neben einer Anpassung der Benutzeroberfläche auch eine Berechnung in der Logikschicht und ein neues Feld in der Datenhaltung erfordern. Werden die Schichten in separaten Projekten organisiert und von eigenen Teams entwickelt, kann der Aufwand selbst bei kleinen Änderungen beträchtlich sein.

Die Struktur der Abhängigkeiten ist in der Praxis allerdings komplexer, als es Abbildung 1 zeigt. Servicebeziehungen ziehen sich unübersichtlich durch die Anwendung und erschweren sowohl Änderungen als auch das Refactoring erheblich (Abb. 2).

Vertical Slice Architecture
Im Gegensatz zu horizontalen Schichten wird der Code bei der Vertical Slice Architecture in vertikalen Scheiben, sogenannten Slices, organisiert. Ein Slice durchdringt den gesamten Stack und bildet eine vollständige fachliche Funktion, ein Feature, ab. Jedes Slice ist in sich geschlossen – self-contained – und enthält alle Komponenten, die zur Umsetzung eines Use Case benötigt werden. Änderungen können daher an einer einzigen Stelle vorgenommen werden.

Neue Funktionalitäten werden in zusätzlichen Slices implementiert, wodurch der bestehende Code nicht geändert werden muss.
Ein Slice kann von einem einzelnen Entwickler bearbeitet werden, ohne dass Absprachen mit anderen Teams erforderlich sind. Dadurch sinkt das Risiko, dass andere Funktionen unbeabsichtigt beeinträchtigt werden. Die Vertical Slice Architecture reduziert oder vermeidet eine Kopplung zwischen den Slices und maximiert die Kohäsion, also den internen Zusammenhalt innerhalb eines Slice.
Aufbau eines Slice
Ein Feature in der Vertical Slice Architecture implementiert einen Use Case, der durch ein externes Ereignis ausgelöst wird – etwa das Drücken eines Buttons seitens des Nutzers –,
das eine POST-Anfrage an ein API sendet.

Ein Controller nimmt die Anfrage entgegen und erzeugt eine Nachricht, die an einen Mediator weitergeleitet wird. Bei der Nachricht handelt es sich entweder um eine Abfrage oder einen Befehl. GET-Aufrufe führen in der Regel zu Abfragen, während POST oder PUT mit einem Befehl abgebildet werden.
Der Einsatz eines Mediators ist optional, wird jedoch häufig zur Entkopplung verwendet. Der Mediator ermittelt einen passenden Handler, der die Anfrage verarbeiten kann. Der Handler führt die Geschäftslogik aus und greift z. B. auf ein Repository zu, um Änderungen in der Datenbank vorzunehmen. Falls eine Antwort erforderlich ist, wird diese auf demselben Weg zurückgesendet. Der gesamte Code zur Verarbeitung einer Anfrage befindet sich in einer einzigen Datei. Jede Benutzeranfrage bildet ein eigenes Slice, das in einer separaten Datei organisiert wird.
Dieser Prozess folgt dem grundlegenden EVA-Prinzip (Eingabe, Verarbeitung, Ausgabe). Der Controller ruft den Handler nicht direkt auf, sondern übergibt die Nachricht an den Mediator. Dieser sorgt dafür, dass vor der Ausführung des Handlers übergreifende Aspekte (Cross-cutting Concerns) wie Validierung oder Sicherheitsprüfungen berücksichtigt werden.

Codebeispiel mit Java und Spring Boot
Während es für C# und .NET zahlreiche Codebeispiele zur Vertical Slice Architecture gibt – oft unter Verwendung des MediatoR-Frameworks von Jimmy Bogard –, ist für Java kaum ein Beispiel zu finden. Ein Mediator ist bei der Nutzung von Spring Boot nicht zwingend erforderlich. Um dennoch eine vergleichbare Implementierung in Java zu ermöglichen, hat der Autor den JMediator entwickelt. Der JMediator ist eine minimale Implementierung und als Spring Boot Starter verfügbar.
Listing 1
@RestController
class CancelOrderApi {
JMediator mediator;
public CancelOrderApi(JMediator mediator) {
this.mediator = mediator;
}
@PutMapping ("/orders/{id}/cancel")
void cancel(@PathVariable UUID id) throws Throwable {
mediator.send(new CancelOrderCommand(id));
}
}
record CancelOrderCommand(UUID id) implements IRequest<Void> { }
@Handler
class CancelHandler {
OrderRepository repo;
public CancelHandler(OrderRepository repo) {
this.repo = repo;
}
void cancel(CancelOrderCommand command) {
Order order = repo.findById(command.id()).orElseThrow();
if (order.getState() != ORDERED)
throw new WrongStateException();
order.setState(CANCELED);
repo.save(order);
}
}
PUT /orders/{id}/cancel
Im Vergleich mit den Schichtenarchitekturen …
In der Vertical Slice Architecture gibt es keine Schichten, die in der gesamten Anwendung sichtbar sind. Die einzelnen Features werden aber meist intern ebenfalls in Schichten unterteilt. Die Anzahl und der Aufbau dieser Schichten können sich, wie in Abbildung 6 rechts dargestellt, von Slice zu Slice unterscheiden.

In einer klassischen Schichtenarchitektur lassen sich UI- oder Datenbankkomponenten relativ einfach austauschen. Allerdings stellt sich die Frage, was häufiger Änderungen unterliegt: die Datenbanktechnologie oder die fachlichen Anforderungen? Die Vertical Slice Architecture ist darauf ausgelegt, Änderungen und Erweiterungen der Fachlichkeit optimal zu unterstützen.
… und mit Microservices
Auf den ersten Blick zeigt die Vertical Slice Architecture Ähnlichkeiten mit der Microservices-Architektur, unterscheidet sich von dieser jedoch in wesentlichen Punkten. Ein Microservice verfügt über eine eigene Codebasis und kann unabhängig von anderen Services entwickelt, bereitgestellt und betrieben werden. Im Gegensatz dazu sind die Slices in der Vertical Slice Architecture zwar voneinander getrennt, bleiben jedoch Teil eines gemeinsamen Projekts und werden zusammen bereitgestellt und betrieben. In der Vertical Slice Architecture teilen sich die Features auch eine Datenbank und können dieselben Fachklassen verwenden.
Code Sharing
In Microservices-Architekturen wird kein Code geteilt. Auf den ersten Blick könnte man annehmen, dass das auch bei der Vertical Slice Architecture so ist, da jedes Slice eine Funktion abbildet und unabhängig von anderen Features sein sollte. Jeder Use Case wird in einem separaten Feature implementiert.
Trotzdem ist es möglich und oft sinnvoll, Code zu teilen. Fachklassen können in einem Modell gekapselt werden, das von mehreren Slices verwendet wird. Funktionalitäten, die keinem speziellen Use Case zugeordnet sind, wie Datumsberechnungen oder Utility-Funktionen, lassen sich in Services auslagern (Abb. 6, rechts).
Bei der Vertical Slice Architecture besteht jedoch die Gefahr, dass sich die Architektur bei vermehrter Codeauslagerung von Features in Services im Extremfall der Schichtenarchitektur annähert. Daher sollte sorgfältig abgewogen werden, welche Teile ausgelagert und in manchen Fällen doppelte Codefragmente akzeptiert werden.
Vor- und Nachteile
Die Vertical Slice Architecture bietet eine Reihe von Vorteilen:
-
Konzentration auf die Fachlichkeit: Durch die Organisation nach Use Cases wird die Entwicklung und Wartung erleichtert. Änderungen oder Erweiterungen betreffen in der Regel nur eine begrenzte Anzahl von Dateien, wodurch Seiteneffekte minimiert werden.
-
Bessere Testbarkeit: Die Isolation der Slices ermöglicht das gezielte Testen einzelner Funktionen und Use Cases.
-
Kürzere Einarbeitungszeit: Im Vergleich zu komplexeren Architekturen wie der hexagonalen oder Clean Architecture ist die Vertical Slice Architecture leichter verständlich. Entwickler können schneller produktiv werden, da sie sich auf ein Slice konzentrieren können und den Rest der Anwendung nicht betrachten müssen.
-
Unabhängige Teams: Jedes Slice kann von einem Mitarbeiter oder einem Team bearbeitet werden, ohne ständige Abstimmungen mit anderen Teams.
-
Lose Kopplung: Die Vertical Slice Architecture minimiert Abhängigkeiten zwischen den Slices und verbessert so die Wartbarkeit der Anwendung.
Allerdings bringt die Vertical Slice Architecture auch Nachteile mit sich. Der größte Nachteil sind unzureichende Abstraktionen. Es besteht das Risiko, zu wenig zu abstrahieren, was zu doppeltem Code in mehreren Slices führen kann. Das beeinträchtigt die Wartbarkeit und Wiederverwendbarkeit des Codes.
Fazit
Die Vertical Slice Architecture bietet eine schlankere Alternative für Entwickler, denen die Hexagonale oder Onion Architecture zu komplex erscheint. Ein entscheidender Vorteil ist die kurze Einarbeitungszeit, die es neuen Teammitgliedern ermöglicht, rasch produktiv zu werden. Die Kapselung von Use Cases erinnert an Microservices und bietet einige ihrer Vorteile, ohne den hohen Betriebsaufwand in Kauf nehmen zu müssen.
Links & Literatur
[1] Bogard, Jimmy: „Vertical Slice Architecture“: https://www.jimmybogard.com/vertical-slice-architecture/
[2] Spring-Boot-Starter für den Jmediator: https://github.com/membrane/jmediator-spring-boot-starter
[3] Spring-Boot-Beispiel zur Vertical Slice Architecture: https://github.com/membrane/spring-boot-vertical-slice-architecture